using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;

namespace TestUtil.Equality
{
    /// <summary>
    /// Helps with testing that equality for class <typeparamref name="TUnderTest"/> is transitive, so that if a equals b and b equals c
    /// then a equals c.
    /// </summary>
    /// <remarks>
    /// This class tests equality using <see cref="Object.Equals"/> so any tests of the equality operator should be performed 
    /// seperately.
    /// </remarks>
    public sealed class TransitiveEqualityTestHelper<TUnderTest>
    {
        #region Fields

        private CreateTestObjectCallback<TUnderTest> _createObjectCallback;

        #endregion

        #region Constructor

        /// <summary>
        /// Helps with testing transitive equality.
        /// </summary>
        public TransitiveEqualityTestHelper(CreateTestObjectCallback<TUnderTest> createObjectCallback)
        {
            _createObjectCallback = createObjectCallback;
        }

        #endregion

        # region Public Methods

        /// <summary>
        /// Asserts that symmetric equality rules are adhered to by type <typeparamref name="TUnderTest"/>.
        /// </summary>
        public void PerformTest()
        {
            TUnderTest first = _createObjectCallback();
            TUnderTest second = _createObjectCallback();
            TUnderTest third = _createObjectCallback();

            AssertTransitiveEqualityWorks(first, second, third);
        }

        # endregion

        #region Support Methods

        private static void AssertTransitiveEqualityWorks(TUnderTest first, TUnderTest second, TUnderTest third)
        {
            bool firstEqualsThird = (first.Equals(third));

            bool firstShouldEqualThird = (first.Equals(second) && second.Equals(third));

            Assert.AreEqual(firstShouldEqualThird, firstEqualsThird, "Transitive equality test failed.");
        }

        #endregion
    }
}
